package com.deluxelx.middleware.whitelist;

import com.alibaba.fastjson.JSON;
import com.deluxelx.middleware.whitelist.annotation.DoWhiteList;
import org.apache.commons.beanutils.BeanUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@Aspect
@Component
public class DoJoinPoint {

    private final Logger logger = LoggerFactory.getLogger(DoJoinPoint.class);

    @Resource
    private String whiteListConfig;

    @Pointcut("@annotation(com.deluxelx.middleware.whitelist.annotation.DoWhiteList)")
    public void aopPoint() {

    }

    @Around("aopPoint()")
    public Object doRouter(ProceedingJoinPoint jp) throws Throwable {
        // TODO 获取内容方法，得到连接点的注解
        // method 返回内容 (UserInfo com.deluxelx.whitelist.interfaces.UserController.queryUserInfo(String))
        // method 能够得到切入点的方法（public UserInfo queryUserInfo）和返回类（UserInfo）
        Method method = this.getMethod(jp);
        DoWhiteList whiteList = method.getAnnotation(DoWhiteList.class);

        // TODO 获取切入点方法中所传的参数 userId 的值
        // whiteList.key() 获取在 Controller类上的 @DoWhiteList(key = "userId", returnJson = "....") 中 key 的值
        // jp.getArgs 获取切入点方法中所传的参数 public UserInfo queryUserInfo(@RequestParam String userId) 中 userId 的值
        String keyValue = this.getFiledValue(whiteList.key(), jp.getArgs());
        logger.info("middleware whitelist handler method：{} value：{}", method.getName(), keyValue);
        // TODO 如果对应方法传来的参数为 null 或 “” 则直接返回，不放行
        // (这里为 @RequestParam String userId的值)
        if (null == keyValue || "".equals(keyValue))
            return this.returnObject(whiteList, method);

        String[] split = whiteListConfig.split(",");

        // TODO 白名单过滤
        for (String str: split) {
            if (keyValue.equals(str)) {
                return jp.proceed();    // 执行目标方法
            }
        }

        // TODO 如果 DoWhiteList 注解含有 Key，但 key 与白名单对不上号则拦截
        return this.returnObject(whiteList, method);
    }

    // 返回对象
    private Object returnObject(DoWhiteList whiteList, Method method) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> returnType = method.getReturnType();
        String returnJson = whiteList.returnJson();
        if ("".equals(returnJson)) {
            return returnType.getDeclaredConstructor().newInstance();
        }
        return JSON.parseObject(returnJson, returnType);
    }

    private Method getMethod(JoinPoint jp) throws NoSuchMethodException {
        Signature sig = jp.getSignature();     // 返回当前连接点签名
        MethodSignature methodSignature = (MethodSignature) sig;   // 转换成方法签名
        return jp.getTarget().getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
    }

    // 获取属性值
    private String getFiledValue(String filed, Object[] args) {
        String filedValue = null;
        for (Object arg: args) {
            try {
                if (null == filedValue || "".equals(filedValue)) {
                    filedValue = BeanUtils.getProperty(arg, filed);
                } else {
                    break;
                }
            } catch (Exception e) {
                if (args.length == 1) {
                    return args[0].toString();
                }
            }
        }
        return filedValue;
    }

}
